-
-
Notifications
You must be signed in to change notification settings - Fork 145
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Handle 'Content-Length' requests #129
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
src/Server.php
Outdated
// Content-Length value is not an integer or not a single integer | ||
$this->emit('error', new \Exception('The value of `Content-Length` is not valid')); | ||
return; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
src/Server.php
Outdated
@@ -139,6 +139,19 @@ public function handleRequest(ConnectionInterface $conn, Request $request) | |||
} | |||
} | |||
|
|||
if ($request->hasHeader('Content-Length')) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have you checked this wrt to chunked transfer encoding?
In particular wrt validating requests that contain both chunked transfer encoding AND a Content-Length
?
src/Server.php
Outdated
// stream must emit an 'end' here, because empty data won't be emitted | ||
$stream->emit('end'); | ||
$conn->removeListener('data', array($stream, 'handleData')); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This block appears a bit unclear to me, perhaps you can clarify? The $contentLength
variable is defined in another scope and may not exist here (though this may not cause here due to short-circuit evaluation).
Why is this listener removed (only) here?
df65f14
to
1fd2812
Compare
Ping @clue. I think, I handled all your remarks. |
src/Server.php
Outdated
if ($request->hasHeader('Content-Length')) { | ||
// remove 'Content-Length' header accordig to: https://tools.ietf.org/html/rfc7230#section-3.3.3 | ||
$headers = $request->getHeaders(); | ||
unset($headers['Content-Length']); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm undecided on this (and won't block this), but I'd like to hear some other thoughts on this 👍
How should this be handled? Should this header be removed here?
If a message is received with both a Transfer-Encoding and a
Content-Length header field, the Transfer-Encoding overrides the
Content-Length. Such a message might indicate an attempt to
perform request smuggling (Section 9.5) or response splitting
(Section 9.4) and ought to be handled as an error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have a bit more precised specification in the old RFC(https://www.ietf.org/rfc/rfc2616.txt chapter 4.4)
If a message is received with both a
Transfer-Encoding header field and a Content-Length header field,
the latter MUST be ignored.
This would be easier to handle and a more solid behavior.
src/Server.php
Outdated
$request->getQueryParams(), | ||
$request->getProtocolVersion(), | ||
$headers | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FWIW, this is not particularly reliable and currently does not set the correct remoteAddress
property. (see also above, as I'm not sure this is needed in the first place)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See comment above. I found somethin in the old RFC which might eliminate this behavior.
return $this->writeError($conn, 400); | ||
} | ||
|
||
$stream = new LengthLimitedStream($conn, $contentLength); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if a request has neither chunked transfer encoding nor a Content-Length
header (such as for simple GET requests)? Is this tested?
Should this be part of this PR? (see also #104)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
afaik every test with createGetRequest
would be effected. The tests for this would be the same, to the ones that already exist.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure I get what you're suggesting here and I may be missing something obvious here, but I'm specifically talking about this:
- If this is a request message and none of the above are true, then
the message body length is zero (no message body is present).
https://tools.ietf.org/html/rfc7230#section-3.3.3
Is this correctly covered and tested by this PR or is this not supposed to be part of this PR? See also the PR title and #104.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Edited the first comment. This only closes a part of #104
src/LengthLimitedStream.php
Outdated
if (!$this->closed) { | ||
$this->emit('end'); | ||
$this->close(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if the stream ends before the content length has been reached? (see also chunked transfer encoding)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- If a valid Content-Length header field is present [… and] the sender closes the connection […] before the indicated number of octets are
received, the recipient MUST consider the message to be
incomplete and close the connection.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A error handling is missing here. Also in the ChunkedDecoder
I would like to keep it out of this PR because it is currently the same state as ChunkedDecoder
. I will open a separted PR for this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See latest commit. An error will be emitted, so the behavior is the same like in ChunkedDecoder
. I would prefer to add an error handling in an sperarted PR.
$request->on('end', $endEvent); | ||
$request->on('close', $closeEvent); | ||
$request->on('error', $errorEvent); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This whole event will not be emitted anyway? Can be simplified a lot, see also other test cases 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wanted to show that the correct events will be used/not used. But ok.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's exactly what I'm suggesting here :-) The whole request
will not be emitted (which is not tested), as such no events can be emitted on the non-existent request object :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you commented the wrong test, that's why I was so confused. I think you wanted to mark the testNonInteger... tests here. In that case, I agree with you :)
018c48c
to
e2bdac3
Compare
e2bdac3
to
39eb913
Compare
Ping @clue . Rebased and squashed some commits. I hope this good to review, if not just say it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently
Content-Length
requests aren't checked for the transferred length.The new class ensures that only the correct length will be transferred and a correct
end
event will be emitted.